#include "RpcCodec.h"
#include "../proto/rpc.pb.h"
#include "../protobuf/ProtobufCodecLite.h"
// #include "../../net/Buffer.h"
#include <string>
#include <stdio.h>

using namespace yhaida;
using namespace yhaida::rpc;
using std::string;
void rpcMessageCallback(const yhaida::TcpConnectionPtr &,
                        const yhaida::rpc::RpcMessagePtr &,
                        yhaida::Timestamp)
{
}

yhaida::MessagePtr g_msgptr;
void messageCallback(const TcpConnectionPtr &,
                     const yhaida::MessagePtr &msg,
                     yhaida::Timestamp)
{
  g_msgptr = msg;
}

void print(const Buffer &buf)
{
  printf("encoded to %zd bytes\n", buf.readableBytes());
  for (size_t i = 0; i < buf.readableBytes(); ++i)
  {
    unsigned char ch = static_cast<unsigned char>(buf.peek()[i]);

    printf("%2zd:  0x%02x  %c\n", i, ch, isgraph(ch) ? ch : ' ');
  }
}

const char rpctag[] = "RPC0";

int main()
{
  //     std::shared_ptr<yhaida::rpc::RpcMessage> p2(new yhaida::rpc::RpcMessage());

  //   std::shared_ptr<google::protobuf::Message> p = p2;

  yhaida::rpc::RpcMessage message;
  message.set_type(yhaida::rpc::MessageType::REQUEST);
  message.set_id(2);
  char wire[] = "\0\0\0\x13"
                "RPC0"
                "\x08\x01\x11\x02\0\0\0\0\0\0\0"
                "\x0f\xef\x01\x32";
  string expected(wire, sizeof(wire) - 1);
  string s1, s2;
  yhaida::Buffer buf1, buf2;
  {
    // yhaida::ProtobufCodecLiteT<yhaida::rpc::RpcMessage,yhaida::rpc::rpctag> codec(rpcMessageCallback);
    RpcCodec codec(rpcMessageCallback);
    codec.fillEmptyBuffer(&buf1, message);
    print(buf1);
    s1 = std::string(buf1.peek(), buf1.readableBytes());
  }

  {
    yhaida::ProtobufCodecLite codec(&yhaida::rpc::RpcMessage::default_instance(), "RPC0", messageCallback);
    codec.fillEmptyBuffer(&buf2, message);
    print(buf2);
    s2 = std::string(buf2.peek(), buf2.readableBytes());
    codec.onMessage(TcpConnectionPtr(), &buf1, yhaida::Timestamp::now());//解析buf1里面的内容
    assert(g_msgptr);
    assert(g_msgptr->DebugString() == message.DebugString());
    g_msgptr.reset();
  }
  assert(s1 == s2);
  assert(s1 == expected);
  assert(s2 == expected);

  {
    yhaida::Buffer buf;
    yhaida::ProtobufCodecLite codec(&yhaida::rpc::RpcMessage::default_instance(), "XYZ", messageCallback);
    codec.fillEmptyBuffer(&buf, message);
    print(buf);
    s2 = std::string(buf2.peek(), buf2.readableBytes());
    codec.onMessage(TcpConnectionPtr(), &buf, yhaida::Timestamp::now());
    assert(g_msgptr);
    assert(g_msgptr->DebugString() == message.DebugString());
  }

  google::protobuf::ShutdownProtobufLibrary();
}

// ProtobufCodecLite.h:62:9: note:   no known conversion for argument 3
// from
//  ‘const ProtobufMessageCallback
//  {aka
//     const std::function<void(const std::shared_ptr<yhaida::TcpConnection>&,
//     const std::shared_ptr<yhaida::rpc::RpcMessage>&,
//     yhaida::Timestamp)>}’

// to
// ‘const ProtobufMessageCallback&
// {aka const std::function<void(const std::shared_ptr<yhaida::TcpConnection>&,
//     const std::shared_ptr<google::protobuf::Message>&,
//     yhaida::Timestamp)>&}’
